#include "stackshapmanager.h"
#include "algorithm_log.h"
#include "stacksetting.h"
StackShapManager::StackShapManager()
{}

StackShapManager::~StackShapManager()
{}

int StackShapManager::Init()
{
	if (!StackSetting::GetInstance()->Init()) {
		log_error("stack config file read failed");
		return -1;
	}
	m_fixstackmap.clear();
	m_stackmap.clear();

	auto ids = StackSetting::GetInstance()->GetStackIdList();
	for (auto& id : ids) {
		auto cfg = StackSetting::GetInstance()->GetStackCfgById(id);
		if (cfg.id() != id) {
			log_error("load stack setting failed for stack {}", id);
			continue;
		}
		stack::StackCfg data = {};
		data.id = cfg.id();
		data.evenType = cfg.evenType();
		data.gap = cfg.gap();
		data.maxNum = cfg.max();
		data.name = cfg.name();
		for (auto& iter : cfg.position()) {
			stack::SkuPos pos;
			pos.fix.id = iter.id();
			pos.fix.group = iter.group();
			pos.fix.x = iter.x();
			pos.fix.y = iter.y();
			pos.fix.z = iter.z();
			pos.fix.za = iter.za();
			data.pos.append(pos);
		}
		data.shap = cfg.shap();
		data.sku.height = cfg.sku().height();
		data.sku.length = cfg.sku().length();
		data.sku.width = cfg.sku().width();

		StackShap* stack = new StackShap();
		bool ret = stack->Init(data);
		if (ret) {
			if (stack->IsFixed()) {
				m_fixstackmap.insert(id, stack);
			} else {
				m_stackmap.insert(id, stack);
			}
			log_trace("stack id {} name {} load successed", data.id, data.name);
		} else {
			delete stack;
			log_error("stack id {} name {} load failed", data.id, data.name);
		}
	}

	return m_fixstackmap.size() + m_stackmap.size();
}
/****************************************************************************
 * 功能: 根据物料尺寸信息选择垛形
 * 传参: sku:物料尺寸, plate:托盘尺寸
 * 返回值: 成功返回正确的垛形信息id >0;
 ****************************************************************************/
stack::StackInfo StackShapManager::ChooseStackForSku(const Size& sku, const Size& plate)
{
	/*先匹配固定尺寸垛形，匹配成功后直接返回*/
	for (auto& iter : m_fixstackmap) {
		if (iter->CheckSkuMatchStack(sku, plate) > 0) {
			stack::StackInfo info = {};
			info.id = iter->GetId();
			info.name = iter->GetName();
			info.cengNum = iter->GetCengNum();
			info.maxNum = iter->GetMaxNum();
			return info;
		}
	}

	StackShap* p = nullptr;
	int max = 0;
	/*匹配灵活垛形*/
	for (auto& iter : m_stackmap) {
		int ret = iter->CheckSkuMatchStack(sku, plate);
		if (ret > max) {
			max = ret;
			p = iter;
		} else if (ret == max) {
			if (iter->GetCengNum() > p->GetCengNum()) {
				p = iter;
			}
		}
	}
	if (p != nullptr) {
		stack::StackInfo info = {};
		info.id = p->GetId();
		info.name = p->GetName();
		info.cengNum = p->GetCengNum();
		info.maxNum = p->GetMaxNum();
		return info;
	}
	return {};
}
/****************************************************************************
 * 功能: 获取物料坐标
 * 传参: id:垛形编号，sku:物料尺寸,odd 奇数层/偶数层， skupos:输出的物料信息
 * 返回值: 获取是否成功
 ****************************************************************************/
bool StackShapManager::GetSkuPosition(int id, const Size& sku, bool odd, QVector<stack::SkuPosInfo>& skupos)
{
	StackShap* p = nullptr;
	if (m_fixstackmap.find(id) != m_fixstackmap.end()) {
		p = m_fixstackmap[id];
	} else {
		if (m_stackmap.find(id) == m_stackmap.end()) {
			log_error("Not find this stack for {}", id);
			return false;
		} else {
			p = m_stackmap[id];
		}
	}

	int ceng = p->GetCengNum();
	skupos.clear();
	for (int i = 1; i <= ceng; i++) {
		stack::SkuPosInfo pos = {};
		if (p->GetStackPosForSku(i, sku, pos, odd)) {
			skupos.append(pos);
		} else {
			log_error("Get pos info for index {}， sku size = ({}, {}, {})", i, sku.length, sku.width, sku.height);
			break;
		}
	}

	if (skupos.size() == ceng) {
		return true;
	}
	skupos.clear();
	return false;
}

/****************************************************************************
 * 功能: 获取所有垛形列表
 * 传参:
 * 返回值: id+name
 ****************************************************************************/
QStringList StackShapManager::GetStackList()
{
	QStringList ret;
	for (auto& iter : m_fixstackmap) {
		QString str = QString::number(iter->GetId()) + '.' + iter->GetName();
		ret.append(str);
	}

	for (auto& iter : m_stackmap) {
		QString str = QString::number(iter->GetId()) + '.' + iter->GetName();
		ret.append(str);
	}
	return ret;
}

/****************************************************************************
 * 功能: 获取id对应垛形的信息
 * 传参: id
 * 返回值: id+name
 ****************************************************************************/
stack::StackInfo StackShapManager::GetStackInfoById(int id)
{
	StackShap* p = nullptr;
	if (m_fixstackmap.find(id) != m_fixstackmap.end()) {
		p = m_fixstackmap[id];
	} else {
		if (m_stackmap.find(id) != m_stackmap.end()) {
			p = m_stackmap[id];
		}
	}
	if (p != nullptr) {
		stack::StackInfo info = {};
		info.id = p->GetId();
		info.name = p->GetName();
		info.cengNum = p->GetCengNum();
		info.maxNum = p->GetMaxNum();
		return info;
	}
	log_error("Not find stack for id = {}", id);
	return {};
}
